Add PeripheralAndroidOptions.addServicesInScanResponse#263
Conversation
Android caps the primary BLE advertisement at 31 bytes. A 128-bit service UUID (18 bytes) plus the device name overflows it, so startAdvertising fails with ADVERTISE_FAILED_DATA_TOO_LARGE. Add PeripheralAndroidOptions.addServicesInScanResponse: when true, advertised service UUIDs are placed in the scan response instead of the primary packet (and the device name is kept out of the scan response so it can't overflow there either). Active scanners still receive every UUID. Other platforms manage the advertisement/scan-response split themselves and are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces the addServicesInScanResponse option to PeripheralAndroidOptions across Android, iOS, Dart, and Windows platforms. On Android, this option allows putting advertised service UUIDs in the scan response instead of the primary advertisement to prevent packet overflow, while automatically excluding the device name from the scan response if service UUIDs are present. The feedback suggests improving the documentation for addServicesInScanResponse to explicitly mention that the scan response packet is also limited to 31 bytes and to warn about potential overflows when combined with addManufacturerDataInScanResponse.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…ePeripheralPlugin.kt
| val scanResponseBuilder = AdvertiseData.Builder() | ||
| .setIncludeTxPowerLevel(false) | ||
| .setIncludeDeviceName(localName != null) | ||
| // Device name is already included in the primary advertisement when localName != null. | ||
| // Keeping it out of the scan response saves space for manufacturer data / service UUIDs. | ||
| .setIncludeDeviceName(false) |
| class PeripheralAndroidOptions { | ||
| bool? addManufacturerDataInScanResponse; | ||
| PeripheralAndroidOptions({this.addManufacturerDataInScanResponse}); | ||
|
|
||
| /// Put advertised service UUIDs in the scan response instead of the primary | ||
| /// advertisement. The Android primary advertisement and scan response are | ||
| /// both capped at 31 bytes. A 128-bit service UUID (18 bytes) plus a | ||
| /// device name can overflow the primary packet. | ||
| /// Note: If this is enabled with `addManufacturerDataInScanResponse`, ensure | ||
| /// the combined data fits within the scan response's 31-byte limit. | ||
| bool? addServicesInScanResponse; | ||
| PeripheralAndroidOptions({ | ||
| this.addManufacturerDataInScanResponse, | ||
| this.addServicesInScanResponse, | ||
| }); |
Problem
On Android the primary BLE advertisement is capped at 31 bytes. A 128-bit service UUID (18 bytes) plus the device name overflows it, and
startAdvertisingfails withADVERTISE_FAILED_DATA_TOO_LARGE. There is currently no way to move service UUIDs into the scan response — onlyaddManufacturerDataInScanResponseexists — so a peripheral that advertises a 128-bit service UUID and a name cannot advertise at all.Change
Adds
PeripheralAndroidOptions.addServicesInScanResponse. Whentrue, advertised service UUIDs are placed in the scan response instead of the primary advertisement packet. The device name is also kept out of the scan response in that case, so a name + 128-bit UUID can't overflow the scan response either. Active scanners still receive every service UUID.false→ unchanged behavior.Testing
flutter analyzeclean.test/android_options_test.dartround-trip passes with the new field.🤖 Generated with Claude Code